﻿using SAIM.Models;
using SAIM.Models.BLL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.IO;
using MvcFileUploader.Models;
using MvcFileUploader;
using Hangfire;
using Hangfire.SqlServer;

namespace SAIM.Controllers
{
    [Authorize]
    public class TicketsController : Controller
    {
        private SAIMIdentity UserIdentity
        {
            get { return new SAIMIdentity(User.Identity); }
        }

        public enum TicketsMessage
        {
            TicketCreatedSuccessfully,
            TicketClosedSuccessfully,
            TicketOpenedSuccessfully,
            TicketCommentedSuccessfully,
            CommentModifySuccessfully,
            CommentDeleteSuccessfully,
            UserAddedSuccessfully,
            UserRemovedSuccessfully
        }

        //GET: Tickets/Index
        public ActionResult Index(TicketsMessage? message)
        {
            using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
            using (TicketsBLL tickets = new TicketsBLL())
            {
                if (user.isInRole("Services"))
                {
                    ViewBag.StatusMessage = GetStatusMessage(message);
                    return View();
                }
                else throw new HttpException(403, "Acces Denied");
            }
        }

        // GET: Tickets/New
        public ActionResult New(TicketsMessage? message)
        {
            using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
            {
                if (user.isInRole("Create tickets"))
                {
                    if (user.isInRole("Manage tickets"))
                        return View(new NewTicketsViewModel(user.GetAllUsers()));
                    else
                        return View(new NewTicketsViewModel());
                }
                else throw new HttpException(403, "Acces Denied");
            }
        }

        //
        // POST: Tickets/New
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult New(NewTicketsViewModel model)
        {
            using (AspNetUsersBLL actualUser = new AspNetUsersBLL(UserIdentity.GetUserId()))
            {
                if (actualUser.isInRole("Create tickets"))
                {
                    if (ModelState.IsValid)
                    {
                        using (TicketsBLL tickets = new TicketsBLL())
                        {
                            model.User = (model.User != string.Empty && model.User != null) ? model.User : UserIdentity.GetUserId();
                            long ticketId = tickets.Insert(
                                model.User,
                                model.Issue > 0 ? model.Issue : model.Area,
                                DateTime.Now,
                                model.Details,
                                string.Empty);
                            if (ticketId < 1)
                                ModelState.AddModelError("", "Imposible crear ticket, intente más tarde.");
                            else
                            {
                                // Application was added succesfully, returns an empty model
                                using (AspNetUsersBLL user = new AspNetUsersBLL(model.User))
                                {
                                    model.User = user.getUserName();
                                    string url = Request.Url.Scheme + "://" + Request.Url.Host + ":" + Request.Url.Port + "/Tickets/Summary/" + ticketId.ToString();
                                    List<string> emails = tickets.GetAdminsEmails(model.Area);
                                    using (NotificationsBLL notification = new NotificationsBLL(emails))
                                    {
                                        notification.NewTicket(model, url, user.Value.Id);
                                    }
                                    emails.Add(user.getUserEmail());
                                    JobStorage.Current = new SqlServerStorage(
                                        "SAIMHangFire",
                                        new SqlServerStorageOptions { QueuePollInterval = TimeSpan.FromSeconds(1) });
                                    BackgroundJob.Enqueue(() => NewTicketEmail.NotifyNewTicket(model, ticketId, url, emails));
                                    return RedirectToAction("Manage", new { message = TicketsMessage.TicketCreatedSuccessfully });
                                }
                            }
                        }
                        return View(model);
                    }

                    return View(model);
                }
                else throw new HttpException(403, "Acces Denied");
            }
        }

        // GET: Tickets/Summary
        public ActionResult Summary(long? Id, TicketsMessage? message)
        {
            string parentIssue;

            if (Id == null)
            {
                return RedirectToAction("Index");
            }
            else
            {
                using (TicketsBLL tickets = new TicketsBLL())
                {
                    try
                    {
                        parentIssue = tickets.Get(Id.Value).Issues.ParentIssue.Name;
                        switch (parentIssue)
                        {
                            case "Administración":
                                return RedirectToAction("AdministrationTicket", new { Id = Id, message = message });
                            case "TIC":
                                return RedirectToAction("TICTicket", new { Id = Id, message = message });
                            case "Mantenimiento":
                                return RedirectToAction("MaintenanceTicket", new { Id = Id, message = message });
                            default:
                                using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
                                {

                                    if (user.isInRole("Maintenance Tickets") || user.isInRole("RTIC Tickets") || user.isInRole("Administration Tickets"))
                                    {
                                        try
                                        {
                                            ViewBag.StatusMessage = GetStatusMessage(message);
                                            return View(new TicketData(tickets.Get(Id.Value)));
                                        }
                                        catch (Exception)
                                        {
                                            return RedirectToAction("Index");
                                        }
                                    }
                                    else
                                    {
                                        try
                                        {
                                            ViewBag.StatusMessage = GetStatusMessage(message);
                                            return View(new TicketData(tickets.Get(Id.Value, user.Value.Id)));
                                        }
                                        catch (Exception)
                                        {
                                            return RedirectToAction("Index");
                                        }
                                    }
                                }
                        }
                    }
                    catch (Exception)
                    {
                        return RedirectToAction("Index");
                    }
                }
            }
        }

        // GET: Tickets/AdministrationTicket
        public ActionResult AdministrationTicket(long? Id, TicketsMessage? message)
        {
            if (Id == null)
            {
                return RedirectToAction("Index");
            }
            else
            {
                using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
                {
                    if (user.isInRole("Manage tickets") && user.IsInArea("Administración"))
                    {
                        return ShowTicket(Id, message, user, true, "Administración");
                    }
                    else
                    {
                        return ShowTicket(Id, message, user, false, "Administración");
                    }
                }
            }
        }

        // GET: Tickets/TICTicket
        public ActionResult TICTicket(long? Id, TicketsMessage? message)
        {
            if (Id == null)
            {
                return RedirectToAction("Index");
            }
            else
            {
                using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
                {
                    if (user.isInRole("Manage tickets") && user.IsInArea("TIC"))
                    {
                        return ShowTicket(Id, message, user, true, "TIC");
                    }
                    else
                    {
                        return ShowTicket(Id, message, user, false, "TIC");
                    }
                }
            }
        }

        // GET: Tickets/MaintenanceTicket
        public ActionResult MaintenanceTicket(long? Id, TicketsMessage? message)
        {
            if (Id == null)
            {
                return RedirectToAction("Index");
            }
            else
            {
                using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
                {
                    if (user.isInRole("Manage tickets") && user.IsInArea("Mantenimiento"))
                    {
                        return ShowTicket(Id, message, user, true, "Mantenimiento");
                    }
                    else
                    {
                        return ShowTicket(Id, message, user, false, "Mantenimiento");
                    }
                }
            }
        }

        private ActionResult ShowTicket(long? Id, TicketsMessage? message, AspNetUsersBLL user, bool isAdmin, string ticketArea)
        {
            try
            {
                using (TicketsBLL tickets = new TicketsBLL())
                {
                    string parentIssue = tickets.Get(Id.Value).Issues.ParentIssue.Name;
                    if (parentIssue != ticketArea)
                    {
                        return RedirectToAction("Summary", new { Id = Id, message = message });
                    }
                    if (isAdmin)
                    {
                        ViewBag.StatusMessage = GetStatusMessage(message);
                        return View(new TicketData(tickets.Get(Id.Value)));
                    }
                    else
                    {
                        ViewBag.StatusMessage = GetStatusMessage(message);
                        return View(new TicketData(tickets.Get(Id.Value, user.Value.Id)));
                    }
                }
            }
            catch (Exception)
            {
                return RedirectToAction("Index");
            }
        }

        //GET: Tickets/Manage
        public ActionResult Manage(TicketsMessage? message)
        {
            using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
            {
                if (user.isInRole("Maintenance Tickets") || user.isInRole("RTIC Tickets") || user.isInRole("Administration Tickets"))
                {
                    using (TicketsBLL tickets = new TicketsBLL())
                    {
                        ViewBag.StatusMessage = GetStatusMessage(message);
                        return View();
                    }
                }
                else
                {
                    return RedirectToAction("Index", new { message = message });
                }
            }
        }

        public ActionResult File(long? Id)
        {
            string parentIssue;

            if (Id == null)
            {
                return RedirectToAction("Index");
            }
            else
            {
                using (TicketsBLL tickets = new TicketsBLL())
                {
                    try
                    {
                        var ticketFound = tickets.Get(Id.Value);
                        parentIssue = ticketFound.Issues.ParentIssue.Name;
                        using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
                        {
                            switch (parentIssue)
                            {
                                case "TIC":
                                    if (user.isInRole("Manage tickets") && user.IsInArea("TIC"))
                                    {
                                        return new Rotativa.ViewAsPdf("File", new TicketData(tickets.Get(Id.Value))) 
                                        { 
                                            PageSize = Rotativa.Options.Size.A4,
                                            FileName = "Formato de Reporte (Ticket número " + Id.Value.ToString() + ").pdf"
                                        };
                                        // Retornar vista para realizar pruebas
                                        //return View(new TicketData(tickets.Get(Id.Value)));
                                    }
                                    break;
                                case "Administración":
                                    if (user.isInRole("Manage tickets") && user.IsInArea("Administración"))
                                    {
                                        return new Rotativa.ViewAsPdf("File", new TicketData(tickets.Get(Id.Value)))
                                        {
                                            PageSize = Rotativa.Options.Size.A4,
                                            FileName = "Formato de Reporte (Ticket número " + Id.Value.ToString() + ").pdf"
                                        };
                                        // Retornar vista para realizar pruebas
                                        //return View(new TicketData(tickets.Get(Id.Value)));
                                    }
                                    break;
                            }
                            // Si el usuario no tiene permisos para administrar el ticket obtiene el ticket con dicho Id. 
                            // En cado de que el usuario no tenga los permisos necesarios  se lanza una excepción
                            return new Rotativa.ViewAsPdf("File", new TicketData(tickets.Get(Id.Value, user.Value.Id)))
                            {
                                PageSize = Rotativa.Options.Size.A4,
                                FileName = "Formato de Reporte (Ticket número " + Id.Value.ToString() + ").pdf"
                            };
                            // Retornar vista para realizar pruebas
                            //return View(new TicketData(tickets.Get(Id.Value, user.Value.Id)));
                        }
                    }
                    catch (Exception) // Si ocurre un error se redirige hacia Index
                    {
                        return RedirectToAction("Index");
                    }
                }
            }
        }

        [HttpPost]
        public ActionResult GetTickets(int current, int rowCount, Dictionary<object, string> sort, string searchPhrase, DateTime? init, DateTime? end, string status, string userId)
        {
            int _current = current;
            int _rowCount = rowCount;
            int _total = 0;
            using (AspNetUsersBLL user = new AspNetUsersBLL(userId == null ? UserIdentity.GetUserId() : userId))
            {
                if ((user.isInRole("Maintenance Tickets") || user.isInRole("RTIC Tickets") || user.isInRole("Administration Tickets")) && (userId == null))
                {
                    using (TicketsBLL tickets = new TicketsBLL())
                    {
                        List<string> rolesTickets = user.GetRolesForTickets();
                        return new JsonResult()
                        {
                            Data = new TicketsViewModel(tickets.GetTicketsAdmin(rolesTickets, current, rowCount, sort, searchPhrase, init != null ? init.Value : DateTime.Now, end != null ? end.Value : DateTime.Now, status, ref _total))
                            {
                                current = _current,
                                rowCount = _rowCount,
                                total = _total
                            }
                        };
                    }
                }
                else
                {
                    if (UserIdentity.GetUserId() == userId)
                        using (TicketsBLL tickets = new TicketsBLL())
                        {
                            return new JsonResult()
                            {
                                Data = new TicketsViewModel(tickets.GetTickets(userId, current, rowCount, 
                                    sort, searchPhrase, init != null ? init.Value : DateTime.Now, 
                                    end != null ? end.Value : DateTime.Now, status, ref _total))
                                {
                                    current = _current,
                                    rowCount = _rowCount,
                                    total = _total
                                }
                            };
                        }
                    else
                        throw new HttpException(403, "Acces Denied");
                }
            }
        }

        /// <summary>
        /// ## Partial View ##
        /// Shows an Issue with their Sub-Issues
        /// </summary>
        /// <param name="Id">Issue Id</param>
        /// <returns></returns>
        public ActionResult _GetIssues(long Id)
        {
            return PartialView(new NewTicketsViewModel(Id));
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult AddComment(TicketComment model)
        {
            if (ModelState.IsValid)
            {
                using (TicketsBLL ticket = new TicketsBLL())
                using (TicketCommentsBLL comment = new TicketCommentsBLL())
                {
                    model.CommentDate = DateTime.Now;
                    model.UserName = UserIdentity.GetUserName();
                    comment.insertComment(model.IdTicket, UserIdentity.GetUserId(), model.Comment, model.CommentDate, model.IsPrivate, model.HasAttachedFiles);
                    string url = Request.Url.Scheme + "://" + Request.Url.Host + ":" + Request.Url.Port + "/Tickets/Summary/" + model.IdTicket;
                    List<string> usersIdList, userEmailsList;
                    if (model.IsPrivate)
                    {
                        // Obtenemos los ID'S de usuario y los emails para los administradores del ticket
                        string area = ticket.Get(model.IdTicket).Issues.ParentIssue.Name;
                        usersIdList = ticket.GetAdminsId(area);
                        userEmailsList = ticket.GetAdminsEmails(area);
                    }
                    else 
                    {
                        // Obtenemos los ID'S de usuario y los emails para todos los usuarios del ticket
                        usersIdList = ticket.GetUsersId(model.IdTicket);
                        userEmailsList = ticket.GetUsersEmails(model.IdTicket);
                    }
                    using (NotificationsBLL notification = new NotificationsBLL(usersIdList))
                    {
                        notification.NewTicketComment(model, url, UserIdentity.GetUserId());
                    }
                    JobStorage.Current = new SqlServerStorage(
                        "SAIMHangFire",
                        new SqlServerStorageOptions { QueuePollInterval = TimeSpan.FromSeconds(1) });
                    BackgroundJob.Enqueue(() => NewCommentEmail.NotifyNewComment(model, url, userEmailsList));
                    if (model.ToggleStatus)
                    {
                        if (ticket.Get(model.IdTicket).Closed)
                            ticket.OpenTicket(model.IdTicket);
                        else
                            ticket.closeTicket(model.IdTicket);
                    }
                }
            }

            return RedirectToAction("Summary", new { Id = model.IdTicket });
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult EditComment(TicketComment model)
        {
            if (ModelState.IsValid)
            {
                using (TicketsBLL ticket = new TicketsBLL())
                using (TicketCommentsBLL comment = new TicketCommentsBLL())
                {
                    model.CommentDate = DateTime.Now;
                    model.UserName = UserIdentity.GetUserName();
                    if (comment.editComment(model.IdTicket, UserIdentity.GetUserId(), model.IdComment, model.Comment, model.CommentDate))
                    {
                        string url = Request.Url.Scheme + "://" + Request.Url.Host + ":" + Request.Url.Port + "/Tickets/Summary/" + model.IdTicket;
                        bool isPrivate = comment.GetTicketComment(model.IdTicket, UserIdentity.GetUserId(), model.IdComment).IsPrivate;
                        List<string> usersIdList, userEmailsList;
                        if (isPrivate)
                        {
                            // Obtenemos los ID'S de usuario y los emails para los administradores del ticket
                            string area = ticket.Get(model.IdTicket).Issues.ParentIssue.Name;
                            usersIdList = ticket.GetAdminsId(area);
                            userEmailsList = ticket.GetAdminsEmails(area);
                        }
                        else
                        {
                            // Obtenemos los ID'S de usuario y los emails para todos los usuarios del ticket
                            usersIdList = ticket.GetUsersId(model.IdTicket);
                            userEmailsList = ticket.GetUsersEmails(model.IdTicket);
                        }
                        using (NotificationsBLL notification = new NotificationsBLL(usersIdList))
                        {
                            notification.TicketCommentEdition(model, url, UserIdentity.GetUserId());
                        }
                        JobStorage.Current = new SqlServerStorage(
                            "SAIMHangFire",
                            new SqlServerStorageOptions { QueuePollInterval = TimeSpan.FromSeconds(1) });
                        BackgroundJob.Enqueue(() => CommentEditionEmail.NotifyCommentEdition(model, url, userEmailsList));
                    }
                }
            }

            return RedirectToAction("Summary", new { Id = model.IdTicket });
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult CloseTicket(CloseTicketViewModel model)
        {
            if (ModelState.IsValid)
            {
                using (TicketsBLL ticket = new TicketsBLL())
                {
                    if (ticket.closeTicket(model.IdTicket))
                        return RedirectToAction("Summary", new { Id = model.IdTicket, message = TicketsMessage.TicketClosedSuccessfully });
                }
            }

            return RedirectToAction("Summary", new { Id = model.IdTicket });
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult OpenTicket(CloseTicketViewModel model)
        {
            if (ModelState.IsValid)
            {
                using (TicketsBLL ticket = new TicketsBLL())
                {
                    if (ticket.OpenTicket(model.IdTicket))
                        return RedirectToAction("Summary", new { Id = model.IdTicket, message = TicketsMessage.TicketOpenedSuccessfully });
                }
            }

            return RedirectToAction("Summary", new { Id = model.IdTicket });
        }

        [HttpPost]
        public ActionResult _GetEditionsByComment(long? IdComment)
        {
            if (IdComment == null)
                throw new HttpException(404, "NotFound");
            else
            {
                using (TicketCommentsBLL comment = new TicketCommentsBLL())
                {
                    return PartialView(new GetEditionsByCommentViewModel(comment.GetEditions(IdComment.Value)));
                }
            }
        }

        //GET: Tickets/Attachments
        public ActionResult Attachments(long? Id, TicketsMessage? message)
        {
            string parentIssue;

            if (Id == null)
            {
                return RedirectToAction("Index");
            }
            else
            {
                using (TicketsBLL tickets = new TicketsBLL())
                {
                    try
                    {
                        var ticketFound = tickets.Get(Id.Value);
                        parentIssue = ticketFound.Issues.ParentIssue.Name;
                        using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
                        {
                            switch (parentIssue)
                            {
                                case "TIC":
                                    if (user.isInRole("Manage tickets") && user.IsInArea("TIC"))
                                    {
                                        ViewBag.StatusMessage = GetStatusMessage(message);
                                        return View(new TicketData(tickets.Get(Id.Value)));
                                    }
                                    break;
                                case "Administración":
                                    if (user.isInRole("Manage tickets") && user.IsInArea("Administración"))
                                    {
                                        ViewBag.StatusMessage = GetStatusMessage(message);
                                        return View(new TicketData(tickets.Get(Id.Value)));
                                    }
                                    break;
                            }
                            // Si el usuario no tiene permisos para administrar el ticket obtiene el ticket con dicho Id. 
                            // En cado de que el usuario no tenga los permisos necesarios  se lanza una excepción
                            ViewBag.StatusMessage = GetStatusMessage(message);
                            return View(new TicketData(tickets.Get(Id.Value, user.Value.Id)));
                        }
                    }
                    catch (Exception) // Si ocurre un error se redirige hacia Index
                    {
                        return RedirectToAction("Index");
                    }
                }
            }
        }

        [HttpPost]
        public ActionResult GetTicketAttachments(long? Id, int current, int rowCount, Dictionary<object, string> sort, string searchPhrase)
        {
            int _current = current;
            int _rowCount = rowCount;
            int _total = 0;

            using (TicketsBLL tickets = new TicketsBLL())
            {
                return new JsonResult()
                {
                    Data = new GridTicketAttachmentsModel(tickets.GetTicketAttachments(current, rowCount, sort, searchPhrase, Id.Value, ref _total))
                    {
                        current = _current,
                        rowCount = _rowCount,
                        total = _total
                    }
                };
            }
        }
        
        //--------------------------------------------Se ejecuta cuando se va descargar un archivo.------------------------------------------------
        public ActionResult GetAttachedFile(string id, string attachmentId)
        {
            long ticketId;
            string filePath, fileName, parentIssue;

            filePath = fileName = string.Empty;
            if ((id == null) || !long.TryParse(id, out ticketId))
                throw new HttpException(404, "Page Not Found");

            using (TicketsBLL tickets = new TicketsBLL())
            {
                var ticketFound = tickets.Get(ticketId);
                if (ticketFound != null)
                {
                    parentIssue = ticketFound.Issues.ParentIssue.Name;
                    using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
                    {
                        switch (parentIssue)
                        {
                            case "TIC":
                                if (user.isInRole("Manage tickets") && user.IsInArea("TIC"))
                                {
                                    if (tickets.Get(ticketId) == null)
                                        throw new HttpException(404, "Page Not Found");
                                }
                                else
                                {
                                    if (tickets.Get(ticketId, UserIdentity.GetUserId()) == null)
                                        throw new HttpException(404, "Page Not Found");
                                }
                                break;
                            case "Administración":
                                if (user.isInRole("Manage tickets") && user.IsInArea("Administración"))
                                {
                                    if (tickets.Get(ticketId) == null)
                                        throw new HttpException(404, "Page Not Found");
                                }
                                else
                                {
                                    if (tickets.Get(ticketId, UserIdentity.GetUserId()) == null)
                                        throw new HttpException(404, "Page Not Found");
                                }
                                break;
                        }
                    }
                }
                else
                {
                    throw new HttpException(404, "Page Not Found");
                }

                using (AttachmentsBLL attachment = new AttachmentsBLL())
                {
                    attachment.GetAttachmentName(ticketId, attachmentId, ref filePath, ref fileName);

                    if (fileName == null)
                        throw new HttpException(404, "Page Not Found");

                    return File(Path.Combine(filePath, attachmentId), "multipart/form-data", fileName);
                }
            }
        }
        //----------------------------------------Se ejecuta cuando se carga un archivo con el MVCUPLOADER-------------------------------------------------------------------------------------------------
        [HttpPost]
        public ActionResult UploadCommentFiles(long? Id) 
        {
            var statuses = new List<ViewDataUploadFileResult>();
            string pathForSaving = Server.MapPath("~/Content/uploads/" + UserIdentity.GetUserId());

            if (Id == null)
            {
                throw new HttpException(404, "Id required");
            }
            // Si no existe el directorio del usuario lo crea
            if(!CreateFolderIfNeeded(pathForSaving))
                throw new HttpException(404, "Can not create file");

            for (var i = 0; i < Request.Files.Count; i++)
            {
                using (AttachmentsBLL attachment = new AttachmentsBLL())
                {
                    var myFile = Request.Files[i];
                    var st = attachment.AttachFile(myFile, UserIdentity.GetUserId(), Id.Value, pathForSaving);
                    if (st.error == null)
                    {
                        statuses.Add(st);
                        using (TicketsBLL ticket = new TicketsBLL())
                        using (TicketCommentsBLL ticketComment = new TicketCommentsBLL())
                        {
                            string host = Request.Url.Scheme + "://" + Request.Url.Host + ":" + Request.Url.Port;
                            string url = host + "/Tickets/Summary/";
                            ticketComment.NewAttachmentComment(Id.Value, UserIdentity.GetUserId(), DateTime.Now, myFile, st.SavedFileName, host);
                        }
                    }
                }
            }
            var viewresult = Json(new { files = statuses });
            //for IE8 which does not accept application/json
            if (Request.Headers["Accept"] != null && !Request.Headers["Accept"].Contains("application/json"))
                viewresult.ContentType = "text/plain";

            return viewresult;
        }
        
        [HttpPost]
        public ActionResult UploadFile(long? Id)
        {
            var statuses = new List<ViewDataUploadFileResult>();
            string pathForSaving = Server.MapPath("~/Content/uploads/" + UserIdentity.GetUserId());

            if (Id == null)
            {
                throw new HttpException(404, "Id required");
            }
            // Si no existe el directorio del usuario lo crea
            if (!CreateFolderIfNeeded(pathForSaving))
                throw new HttpException(404, "Can not create file");

            for (var i = 0; i < Request.Files.Count; i++)
            {
                using (AttachmentsBLL attachment = new AttachmentsBLL())
                {
                    var myFile = Request.Files[i];
                    var st = attachment.AttachFile(myFile, UserIdentity.GetUserId(), Id.Value, pathForSaving);
                    if (st.error == null)
                    {
                        statuses.Add(st);
                        using (TicketsBLL ticket = new TicketsBLL())
                        using (TicketCommentsBLL ticketComment = new TicketCommentsBLL())
                        {
                            string host = Request.Url.Scheme + "://" + Request.Url.Host + ":" + Request.Url.Port;
                            string url = host + "/Tickets/Summary/" + Id.Value.ToString();
                            if (ticketComment.NewAttachmentComment(Id.Value, UserIdentity.GetUserId(), DateTime.Now, myFile, st.SavedFileName, host) == TicketCommentsBLL.TicketCommentsMessage.FileUploadCommentAdded)
                            {
                                TicketComment comment = new TicketComment()
                                {
                                    UserName = UserIdentity.GetUserName(),
                                    IdTicket = Id.Value,
                                    CommentDate = DateTime.Now
                                };
                                using (NotificationsBLL notification = new NotificationsBLL(ticket.GetUsersId(Id.Value)))
                                {
                                    notification.FileUploaded(UserIdentity.GetUserName(), url, UserIdentity.GetUserId(), Id.Value.ToString());
                                }
                                JobStorage.Current = new SqlServerStorage(
                                    "SAIMHangFire",
                                    new SqlServerStorageOptions { QueuePollInterval = TimeSpan.FromSeconds(1) });
                                BackgroundJob.Enqueue(() => FileUploadedEmail.NotifyFileUploaded(comment, url, ticket.GetUsersEmails(comment.IdTicket)));
                            }
                        }
                    }
                }
            }
            var viewresult = Json(new { files = statuses });
            //for IE8 which does not accept application/json
            if (Request.Headers["Accept"] != null && !Request.Headers["Accept"].Contains("application/json"))
                viewresult.ContentType = "text/plain";

            return viewresult;
        }

        // GET: Tickets/_GetFileEditions
        public ActionResult _GetFileEditions(long? id, string fileName)
        {
            using (AttachmentsBLL attachment = new AttachmentsBLL())
            {
                return PartialView(new GetFileEditionsViewModel(attachment.GetAttachmentEditions(id ?? 0, fileName)));
            }
        }

        public ActionResult Users(long? Id, TicketsMessage? message)
        {
            string parentIssue;

            if (Id == null)
            {
                return RedirectToAction("Index");
            }
            else
            {
                using (TicketsBLL tickets = new TicketsBLL())
                {
                    try
                    {
                        var ticketFound = tickets.Get(Id.Value);
                        parentIssue = ticketFound.Issues.ParentIssue.Name;
                        using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
                        {
                            switch (parentIssue)
                            {
                                case "TIC":
                                    if (user.isInRole("Manage tickets") && user.IsInArea("TIC"))
                                    {
                                        ViewBag.StatusMessage = GetStatusMessage(message);
                                        ViewBag.IsAdmin = true;
                                        return View(new TicketData(tickets.Get(Id.Value)));
                                    }
                                    break;
                                case "Administración":
                                    if (user.isInRole("Manage tickets") && user.IsInArea("Administración"))
                                    {
                                        ViewBag.StatusMessage = GetStatusMessage(message);
                                        ViewBag.IsAdmin = true;
                                        return View(new TicketData(tickets.Get(Id.Value)));
                                    }
                                    break;
                            }
                            // Si el usuario no tiene permisos para administrar el ticket obtiene el ticket con dicho Id. 
                            // En cado de que el usuario no tenga los permisos necesarios  se lanza una excepción
                            ViewBag.StatusMessage = GetStatusMessage(message);
                            ViewBag.IsAdmin = false;
                            return View(new TicketData(tickets.Get(Id.Value, user.Value.Id)));
                        }
                    }
                    catch (Exception) // Si ocurre un error se redirige hacia Index
                    {
                        return RedirectToAction("Index");
                    }
                }
            }
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Users(TicketsUsersViewModel model)
        {
            string parentIssue;

            using (TicketsBLL tickets = new TicketsBLL())
            {
                if (ModelState.IsValid)
                {
                    // Agregar usuario colaborador al ticket
                    if (tickets.AddUser(model.TicketId, model.UPN))
                    {
                        string url = Request.Url.Scheme + "://" + Request.Url.Host + ":" + Request.Url.Port + "/Tickets/Users/" + model.TicketId.ToString();
                        using(AspNetUsersBLL user = new AspNetUsersBLL(model.UPN))
                        using(TicketsBLL updatedTicket = new TicketsBLL())
                        using (NotificationsBLL notification = new NotificationsBLL(updatedTicket.GetUsersId(model.TicketId)))
                        {
                            notification.TicketUserAdded(user.getUserName(), model.TicketId.ToString(), url, UserIdentity.GetUserId());
                            JobStorage.Current = new SqlServerStorage(
                                "SAIMHangFire",
                                new SqlServerStorageOptions { QueuePollInterval = TimeSpan.FromSeconds(1) });
                            BackgroundJob.Enqueue(() => TicketUserAddedEmail.NotifyUserAdded(user.getUserName(), model.TicketId.ToString(), url, updatedTicket.GetUsersEmails(model.TicketId)));
                        }
                        ViewBag.StatusMessage = GetStatusMessage(TicketsMessage.UserAddedSuccessfully);
                    }
                    else
                        ModelState.AddModelError("", "Usuario no agregado");
                }
                // Construcción del modelo para la vista y retorno de la vista
                try
                {
                    var ticketFound = tickets.Get(model.TicketId);
                    parentIssue = ticketFound.Issues.ParentIssue.Name;
                    using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
                    {
                        switch (parentIssue)
                        {
                            case "TIC":
                                if (user.isInRole("Manage tickets") && user.IsInArea("TIC"))
                                {
                                    ViewBag.IsAdmin = true;
                                    return View(new TicketData(tickets.Get(model.TicketId)));
                                }
                                break;
                            case "Administración":
                                if (user.isInRole("Manage tickets") && user.IsInArea("Administración"))
                                {
                                    ViewBag.IsAdmin = true;
                                    return View(new TicketData(tickets.Get(model.TicketId)));
                                }
                                break;
                        }
                        // Si el usuario no tiene permisos para administrar el ticket obtiene el ticket con dicho Id. 
                        // En caso de que el usuario no tenga los permisos necesarios  se lanza una excepción
                        ViewBag.IsAdmin = false;
                        return View(new TicketData(tickets.Get(model.TicketId, UserIdentity.GetUserId())));
                    }
                }
                catch (Exception) // Si ocurre un error se redirige hacia Index
                {
                    return RedirectToAction("Index");
                }
            }
        }

        [HttpPost]
        public ActionResult GetTicketUsers(long? Id, int current, int rowCount, Dictionary<object, string> sort, string searchPhrase)
        {
            int _current = current;
            int _rowCount = rowCount;

            using (TicketsBLL tickets = new TicketsBLL())
            {
                return new JsonResult()
                {
                    Data = tickets.GetTicketUsers(current, rowCount, sort, searchPhrase, Id.Value)
                };
            }
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult RemoveUser(TicketsUsersViewModel model)
        {
            string parentIssue;

            using (TicketsBLL tickets = new TicketsBLL())
            using (NotificationsBLL notification = new NotificationsBLL(tickets.GetUsersId(model.TicketId)))
            {
                if (ModelState.IsValid)
                {
                    if (tickets.RemoveUser(model.TicketId, model.UPN))
                    {
                        string url = Request.Url.Scheme + "://" + Request.Url.Host + ":" + Request.Url.Port + "/Tickets/Users/" + model.TicketId.ToString();
                        using (AspNetUsersBLL user = new AspNetUsersBLL(model.UPN))
                        {
                            notification.TicketUserRemoved(user.getUserName(), model.TicketId.ToString(), url, UserIdentity.GetUserId());
                            JobStorage.Current = new SqlServerStorage(
                                "SAIMHangFire",
                                new SqlServerStorageOptions { QueuePollInterval = TimeSpan.FromSeconds(1) });
                            BackgroundJob.Enqueue(() => TicketUserRemovedEmail.NotifyUserRemoved(user.getUserName(), model.TicketId.ToString(), url, tickets.GetUsersEmails(model.TicketId)));
                        }
                        ViewBag.StatusMessage = GetStatusMessage(TicketsMessage.UserRemovedSuccessfully);
                    }
                    else
                        ModelState.AddModelError("", "Usuario no eliminado");
                }
                // Construcción del modelo para la vista y retorno de la vista
                try
                {
                    var ticketFound = tickets.Get(model.TicketId);
                    parentIssue = ticketFound.Issues.ParentIssue.Name;
                    using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
                    {
                        switch (parentIssue)
                        {
                            case "TIC":
                                if (user.isInRole("Manage tickets") && user.IsInArea("TIC"))
                                {
                                    ViewBag.IsAdmin = true;
                                    return View("Users", new TicketData(tickets.Get(model.TicketId)));
                                }
                                break;
                            case "Administración":
                                if (user.isInRole("Manage tickets") && user.IsInArea("Administración"))
                                {
                                    ViewBag.IsAdmin = true;
                                    return View("Users", new TicketData(tickets.Get(model.TicketId)));
                                }
                                break;
                        }
                        // Si el usuario no tiene permisos para administrar el ticket obtiene el ticket con dicho Id. 
                        // En cado de que el usuario no tenga los permisos necesarios  se lanza una excepción
                        ViewBag.IsAdmin = false;
                        return View("Users", new TicketData(tickets.Get(model.TicketId, UserIdentity.GetUserId())));
                    }
                }
                catch (Exception) // Si ocurre un error se redirige hacia Index
                {
                    return RedirectToAction("Index");
                }
            }
        }

        #region Métodos auxiliares

        /// <summary>
        /// Creates the folder if needed.
        /// </summary>
        /// <param name="path">The path.</param>
        /// <returns></returns>
        private bool CreateFolderIfNeeded(string path)
        {
            bool result = true;
            if (!Directory.Exists(path))
            {
                try
                {
                    Directory.CreateDirectory(path);
                }
                catch (Exception)
                {
                    result = false;
                }
            }
            return result;
        }

        /// <summary>
        /// Devuelve la cadena de estatus de mensaje de acuerdo al enumerador recibido  
        /// </summary>
        /// <param name="message">Enumerador que indica la cadena a devolver</param>
        /// <returns></returns>
        private string GetStatusMessage(TicketsMessage? message)
        {
            string statusMessage =
                        message == TicketsMessage.TicketClosedSuccessfully ? "Ticket cerrado exitosamente" :
                        message == TicketsMessage.TicketCommentedSuccessfully ? "Comentario agregado exitosamente" :
                        message == TicketsMessage.CommentModifySuccessfully ? "Comentario modificado exitosamente" :
                        message == TicketsMessage.CommentDeleteSuccessfully ? "Comentario eliminado exitosamente" :
                        message == TicketsMessage.TicketOpenedSuccessfully ? "Ticket abierto exitosamente" :
                        message == TicketsMessage.UserAddedSuccessfully ? "Usuario agregado exitosamente" : 
                        message == TicketsMessage.UserRemovedSuccessfully ? "Usuario eliminado exitosamente" : "";

            return statusMessage;
        }

        #endregion
    }
}